#include "pde_export.h"
#include "pdeDoseEngine.h"
#include "pdeLut.h"
#include "pdeVolume.h"
#include "pdePlan.h"
#include "pdeStructSet.h"
#include "pdeDoseModel.h"
#include "glm/vec4.hpp"
#include "glm/vec3.hpp"
#include "glm/geometric.hpp"

namespace pde {

	int optimize_plan(std::shared_ptr<Nozzle> nozzle,
		std::shared_ptr<VolumeShort> ct,
		std::shared_ptr<Lut> lut,
		std::vector<std::shared_ptr<Roi>> roi_list,
		std::shared_ptr<Plan> plan,
		std::shared_ptr<VolumeFloat> dose) {

		double mu = 1.0;
		for (auto beam : plan->get_beam_list()) {
			for (auto layer : beam->get_layer_list()) {
				for (auto spot : layer->get_spot_list()) {
					spot->set_mu(mu);
					mu += 1.0;
				}
			}
		}

		return 0;

	}

	int calculate_layers(std::shared_ptr<Nozzle> nozzle,
		std::shared_ptr<VolumeShort> ct,
		std::shared_ptr<Lut> lut,
		std::vector<std::shared_ptr<Roi>> roi_list,
		std::shared_ptr<Plan> plan) {
		
		for (auto beam:plan->get_beam_list()) {
			auto layer = Layer::New();
			layer->set_energy(90.0);
			layer->set_range_shift(10.0);

			auto spot = Spot::New();
			spot->set_position(glm::dvec3(1.0, 2.0, 3.0));

			layer->get_spot_list().push_back(spot);

			beam->get_layer_list().push_back(layer);
		}

		return 0;
	}

	 int calculate_idd(std::shared_ptr<Nozzle> nozzle,
		std::shared_ptr<VolumeShort> ct,
		std::shared_ptr<Lut> lut,
		std::shared_ptr<DoseModel> dose_model,
		std::shared_ptr<DoseCurve> curve) {
		 return 0;
	 }
	int calculate_final_dose(std::shared_ptr<Nozzle> nozzle,
		std::shared_ptr<VolumeShort> ct,
		std::shared_ptr<Lut> lut,
		std::shared_ptr<Plan> plan,
		std::shared_ptr<VolumeFloat> dose_phy,
		std::shared_ptr<VolumeFloat> dose_rbe,
		std::shared_ptr<VolumeFloat> dose_let,
		std::shared_ptr<RbeModel> rbe_model, int dose_engine)
	{

		auto ptr = dose_phy->get_voxels();
		auto size = dose_phy->get_size();
		auto origin = dose_phy->get_origin();
		auto spacing = dose_phy->get_spacing();

		glm::dvec3 center; 		
		for (int i=0;i<3;i++) {
			center[i] = origin[i] + 0.5 * size[i] * spacing[i];
		}

		double r = 50; //mm
		for (int k = 0; k < size[2]; k++) {
			for (int j = 0; j < size[1]; j++) {
				for (int i = 0; i < size[0]; i++) {
					glm::dvec3 pos(i*spacing[0]+origin[0], j*spacing[1]+origin[1], k*spacing[2]+origin[2]);
					auto dist = glm::distance(pos, center);
					if (dist < r) {
						ptr[k * size[0] * size[1] + j * size[0] + i] = 100.0;
					} else {
						ptr[k * size[0] * size[1] + j * size[0] + i] = 0.0;
					}
				}
			}
		}

		return 0;
	}

	int collision_check(std::shared_ptr<Nozzle> nozzle,
		std::shared_ptr<VolumeShort> ct,
		float gantry_angle,
		float couch_angle,
		glm::dvec3 iso_center,
		float air_gap) {

		return 0;
	}

	std::vector<double> calculate_air_profile_sigma(std::shared_ptr<DoseModel> dose_model, const std::vector <double>& z_list) {
		std::vector<double> ret;
		return ret;
	}
}
